//
//  ReportWebViewController.swift
//  EyeVisionForPatients
//
//  Created by PMC on 2020/3/9.
//  Copyright © 2020 tao Tao. All rights reserved.
//

import UIKit
import WebKit
import HandyJSON

// MARK: - WKWebView 内存不释放的问题解决
class WeakWebViewScriptMessageDelegate: NSObject, WKScriptMessageHandler {
    weak var scriptDelegate: WKScriptMessageHandler?
    
    init(with delegate: WKScriptMessageHandler) {
        self.scriptDelegate = delegate
        super.init()
    }
    
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        if let delegate = scriptDelegate, delegate.responds(to: #selector(delegate.userContentController(_:didReceive:))) {
            delegate.userContentController(userContentController, didReceive: message)
        }
    }
    
    deinit {
        YSGLog("WeakWebViewScriptMessageDelegate is deinit")
    }
}

enum YSGWebType {
    case report, bannerAds, helpQuestion
}

/// 检查报告 web
class ReportWebViewController: BaseViewController {
    
    private let patientId: String
    private let webType: YSGWebType
    private let htmlStr: String
    
    init(patientId: String = "", htmlStr: String = "", webType: YSGWebType = .report) {
        self.patientId = patientId
        self.webType = webType
        self.htmlStr = htmlStr
        super.init(nibName: nil, bundle: nil)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    deinit {
        webView.removeObserver(self, forKeyPath: "estimatedProgress")
        webView.removeObserver(self, forKeyPath: "title")
        webView.configuration.userContentController.removeScriptMessageHandler(forName: "jumpBrowser")
        YSGLog("ReportWebViewController is deinit")
    }

    private lazy var webView: WKWebView = {
        // 偏好设置
        let preferences = WKPreferences()
        preferences.minimumFontSize = 9
        
        let configuration = WKWebViewConfiguration()
        configuration.preferences = preferences
        configuration.userContentController = WKUserContentController()
        
        // 给webview与swift交互起名字，webview给swift发消息的时候会用到
        configuration.userContentController.add(WeakWebViewScriptMessageDelegate(with: self), name: "jumpBrowser")
        
        let webView = WKWebView(frame: CGRect(x: 0, y: navBarH, width: screenW, height: screenH - navBarH),
                                configuration: configuration)
        webView.navigationDelegate = self
        webView.allowsBackForwardNavigationGestures = true
        return webView
    }()
    
    private lazy var progressView: UIProgressView = {
        let progress = UIProgressView(frame: CGRect(x: 0, y: navBarH + 2, width: screenW, height: 2))
        progress.tintColor = .mainColor
        progress.trackTintColor = .clear
        return progress
    }()
}

// MARK: - Life Circle
extension ReportWebViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        setupNavigation()
        setupUI()
        setupObserver()
    }
    
    override func viewSafeAreaInsetsDidChange() {
        if #available(iOS 11.0, *) {
            super.viewSafeAreaInsetsDidChange()
            let insets = view.safeAreaInsets
            progressView.frame = CGRect(x: 0, y: insets.top + 2, width: screenW, height: 2)
        }
    }
}

// MARK: - 设置
extension ReportWebViewController {
    private func setupUI() {
        view.addSubview(webView)
        view.addSubview(progressView)
        
        switch webType {
        case .report:
            let urlStr = String(format: ApiUrl.htmlUrl, UserDefaults.token, patientId)
            loadRequest(urlStr)
        case .bannerAds:
            let urlStr = String(format: ApiUrl.htmlUrl1, UserDefaults.token)
            loadRequest(urlStr)
        case .helpQuestion:
            loadHTML(htmlStr)
        }
        
    }
    
    private func loadRequest(_ urlStr: String) {
        let url = URL(string: urlStr)
        let urlRequest = URLRequest(url: url!)
        webView.load(urlRequest)
    }
    
    private func loadHTML(_ htmlStr: String) {
        let string = """
            <html> \n
            <head> \n
            <style type=\"text/css\"> \n
            body { font-size: %ldpx; }\n // 字体大小，px是像素
            </style> \n
            </head> \n
            <body>
            <script type='text/javascript'>
            window.onload = function(){\n
            var $img = document.getElementsByTagName('img');\n
            for(var p in $img) { \n
            $img[p].style.width = '100%%'; \n // 图片宽度
            $img[p].style.height ='auto' \n // 高度自适应
            } \n
            }
            </script>%@
            </body>
            </html>
        """
        let html = String(format: string, 45, htmlStr)
        
        webView.loadHTMLString(html, baseURL: nil)
    }
    
    private func setupObserver() {
        // 添加监测网页加载进度的观察者
        webView.addObserver(self, forKeyPath: "estimatedProgress", options: [], context: nil)
        webView.addObserver(self, forKeyPath: "title", options: .new, context: nil)
    }
    
    private func setupNavigation() {
        let backItem = UIBarButtonItem(imageName: "nav_back", target: self, action: #selector(goBackAction))
        let closeItem = UIBarButtonItem(imageName: "close", target: self, action: #selector(closeAction))
        navigationItem.leftBarButtonItems = [backItem, closeItem]
    }
}

// MARK: - Action
extension ReportWebViewController {
    @objc private func goBackAction() {
        if webView.canGoBack {
            webView.goBack()
        } else {
            navigationController?.popViewController(animated: true)
        }
    }
    
    @objc private func closeAction() {
        navigationController?.popViewController(animated: true)
    }
}

// MARK: - KVO监听
extension ReportWebViewController {
    /// KVO 监听进度 必须实现此方法
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        if let obj = object as? WKWebView, obj == webView {
            
            if keyPath == "estimatedProgress" {
                progressView.progress = Float(webView.estimatedProgress)
                if webView.estimatedProgress >= 1.0 {
                    DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3) {
                        self.progressView.progress = 0.0
                    }
                }
            } else if keyPath == "title" {
                navigationItem.title = webView.title
            }
            
        } else {
            super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
        }
    }
}

// MARK: - WKNavigationDelegate
/**
 WKNavigationDelegate 主要处理一些跳转、加载处理操作，WKUIDelegate主要处理JS脚本，确认框，警告框等
 */
extension ReportWebViewController: WKNavigationDelegate {
    /// 页面开始加载时调用
    func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {}
    
    /// 页面加载失败时调用
    func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
        progressView.setProgress(0.0, animated: false)
    }
    
    /// 当内容开始返回时调用
    func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {}
    
    /// 页面加载完成之后调用
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {}
    
    /// 提交发生错误时调用
    func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
        progressView.setProgress(0.0, animated: false)
    }
    
    /// 接收到服务器跳转请求即服务重定向时之后调用
    func webView(_ webView: WKWebView, didReceiveServerRedirectForProvisionalNavigation navigation: WKNavigation!) {}
    
    /// 根据WebView对于即将跳转的HTTP请求头信息和相关信息来决定是否跳转
    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        decisionHandler(.allow)
    }
    
    /// 根据客户端受到的服务器响应头以及response相关信息来决定是否可以跳转
    func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
        decisionHandler(.allow)
    }
    
    /// 需要响应身份验证时调用 同样在block中需要传入用户身份凭证
    func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
        let cred = URLCredential(user: UserDefaults.account, password: UserDefaults.password, persistence: .none)
        challenge.sender?.use(cred, for: challenge)
        completionHandler(.useCredential, cred)
    }
    
    /// 进程被终止时调用
    func webViewWebContentProcessDidTerminate(_ webView: WKWebView) {}
}

// MARK: - JS调用Swift
extension ReportWebViewController: WKScriptMessageHandler {
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        YSGLog("JS传来的数据: \(message.body) - \(message.name)")
        
        if let model = JSONDeserializer<YSGJSModel>.deserializeFrom(json: message.body as? String) {
            let type = model.type ?? .miniApp
            switch type {
            case .miniApp:
                pushMiniProgram(username: model.appid ?? "", path: model.url ?? "")
            case .web:
                pushBrowser(urlStr: model.url ?? "")
            default:
                break
            }
        }
        
        
    }
    
    /// 跳转小程序
    private func pushMiniProgram(username: String, path: String) {
        let req = WXLaunchMiniProgramReq.object()
        req.userName = username//"gh_d792f5cc2936"//"gh_81cce4b0e0c4"
        req.path = path
        req.miniProgramType = .release
        WXApi.send(req)
    }
    
    /// 跳浏览器
    private func pushBrowser(urlStr: String) {
        guard let url = URL(string: urlStr) else { return }
        
        if UIApplication.shared.canOpenURL(url) {
            UIApplication.shared.open(url, options: [:], completionHandler: nil)
        }
    }
}
